package application

import (
	"errors"
	"fmt"
	uuid "github.com/satori/go.uuid"
	"github.com/yyangl/yoyo/registry"
	"github.com/yyangl/yoyo/utils"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"log"
	"net"
)

type Server struct {
	ca       string
	tls      bool
	name     string
	server   *grpc.Server
	listener net.Listener
	register registry.Register
}

func (s *Server) Run(service Service) error {
	if err := s.Start(); err != nil {
		return err
	}
	listener, err := net.Listen("tcp", service.Addr())
	if err != nil {
		log.Printf("TCP Listen err:%v\n", err)
		return err
	}
	s.listener = listener
	fmt.Printf("service run : addr = %s\n", listener.Addr().String())
	defer s.listener.Close()
	err = s.afterStart(service)
	if err != nil {
		return err
	}
	return s.server.Serve(s.listener)
}

func (s *Server) GetServer() *grpc.Server {
	return s.server
}

/**
start
*/
func (s *Server) Start() error {
	return nil
}

func (s *Server) afterStart(service Service) error {
	// TODO register services & found
	if s.register == nil {
		return errors.New("not initialize register")
	}
	key := utils.ResolveServiceKey(service.Name(), uuid.NewV4().String())
	if err := s.register.PutService(key, service.Addr(), service.TTL()); err != nil {
		return err
	}
	return nil
}

func (s *Server) Close() error {
	return s.listener.Close()
}

func (s *Server) Register() error {
	var opts []grpc.ServerOption
	if s.tls {
		if s.ca == "" {
			log.Printf("ca path is empty,please set ca path")
			return errors.New("ca path is empty,please set ca path")
		}
		creds, err := credentials.NewClientTLSFromFile(s.ca, s.name)
		if err != nil {
			log.Printf("create cert error")
			return err
		}
		opts = append(opts, grpc.Creds(creds))
	}
	s.server = grpc.NewServer(opts...)
	return nil
}

func (s *Server) SetRegister(register registry.Register) {
	s.register = register
}
